﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace OOLib
{
   /// <summary>
   /// Factory interface for creating component instances giving a context from which to retrieve deployment values.
   /// </summary>
   public class MultiComponentFactory : ComObjectWrapper, IMultiComponentFactory
   {
      #region Constructors

      /// <summary>
      /// Constructor
      /// </summary>
      /// <remarks>
      /// After using this constructor, the ComObj must be set manually!
      /// </remarks>
      public MultiComponentFactory() :
         base()
      {
         _MultiComponentFactoryImpl = new MultiComponentFactoryImpl(this);
      }

      /// <summary>
      /// Constructor
      /// </summary>
      /// <param name="comObject">COM object</param>
      public MultiComponentFactory(object comObject) :
         base(comObject)
      {
         _MultiComponentFactoryImpl = new MultiComponentFactoryImpl(this);
      }

      #endregion

      #region IMultiComponentFactory

      private MultiComponentFactoryImpl _MultiComponentFactoryImpl;

      /// <summary>
      /// Creates an instance of a component which supports the services specified by the factory. 
      /// </summary>
      /// <param name="serviceSpecifier">Service name</param>
      /// <param name="context">Context the component instance gets its deployment values from</param>
      /// <returns>Returns the component instance.</returns>
      public ComObjectWrapper CreateInstanceWithContext(string serviceSpecifier, ComponentContext context)
      {
         return _MultiComponentFactoryImpl.CreateInstanceWithContext(serviceSpecifier, context);
      }

      /// <summary>
      /// Creates an instance of a component which supports the services specified by the factory, 
      /// and initializes the new instance with the given arguments and context. 
      /// </summary>
      /// <param name="serviceSpecifier">Service name</param>
      /// <param name="arguments">Arguments</param>
      /// <param name="context">Context the component instance gets its deployment values from</param>
      /// <returns>Returns the component instance.</returns>
      public ComObjectWrapper CreateInstanceWithArgumentsAndContext(string serviceSpecifier, object[] arguments, ComponentContext context)
      {
         return _MultiComponentFactoryImpl.CreateInstanceWithArgumentsAndContext(serviceSpecifier, arguments, context);
      }

      /// <summary>
      /// Gets the names of all supported services.
      /// </summary>
      /// <returns>Retunbs a sequence of all service names.</returns>
      public string[] GetAvailableServiceNames()
      {
         return _MultiComponentFactoryImpl.GetAvailableServiceNames();
      }

      #endregion
   }

   /// <summary>
   /// Factory interface for creating component instances giving a context from which to retrieve deployment values.
   /// </summary>
   public interface IMultiComponentFactory
   {
      /// <summary>
      /// Creates an instance of a component which supports the services specified by the factory. 
      /// </summary>
      /// <param name="serviceSpecifier">Service name</param>
      /// <param name="context">Context the component instance gets its deployment values from</param>
      /// <returns>Returns the component instance.</returns>
      ComObjectWrapper CreateInstanceWithContext(string serviceSpecifier, ComponentContext context);

      /// <summary>
      /// Creates an instance of a component which supports the services specified by the factory, 
      /// and initializes the new instance with the given arguments and context. 
      /// </summary>
      /// <param name="serviceSpecifier">Service name</param>
      /// <param name="arguments">Arguments</param>
      /// <param name="context">Context the component instance gets its deployment values from</param>
      /// <returns>Returns the component instance.</returns>
      ComObjectWrapper CreateInstanceWithArgumentsAndContext(string serviceSpecifier, object[] arguments, ComponentContext context);

      /// <summary>
      /// Gets the names of all supported services.
      /// </summary>
      /// <returns>Retunbs a sequence of all service names.</returns>
      string[] GetAvailableServiceNames();
   }

   /// <summary>
   /// Implementation of the IMultiServiceFactory interface
   /// </summary>
   internal class MultiComponentFactoryImpl : IMultiComponentFactory
   {
      /// <summary>
      /// Constructor
      /// </summary>
      /// <param name="cow">COM object which should support the interface.</param>
      public MultiComponentFactoryImpl(ComObjectWrapper cow)
      {
         Cow = cow;
      }

      /// <summary>
      /// Gets the COM object wrapper which should support the interface.
      /// </summary>
      public ComObjectWrapper Cow { get; private set; }

      /// <summary>
      /// Creates an instance of a component which supports the services specified by the factory. 
      /// </summary>
      /// <param name="serviceSpecifier">Service name</param>
      /// <param name="context">Context the component instance gets its deployment values from</param>
      /// <returns>Returns the component instance.</returns>
      /// <remarks>!!! Not tested !!!</remarks>
      public ComObjectWrapper CreateInstanceWithContext(string serviceSpecifier, ComponentContext context)
      {
         Cow.CheckDisposed();
         return ComObjectWrapper.GetObjectWrapper<ComObjectWrapper>(Cow.InvokeMethod("createInstanceWithContext", serviceSpecifier, context));
      }

      /// <summary>
      /// Creates an instance of a component which supports the services specified by the factory, 
      /// and initializes the new instance with the given arguments and context. 
      /// </summary>
      /// <param name="serviceSpecifier">Service name</param>
      /// <param name="arguments">Arguments</param>
      /// <param name="context">Context the component instance gets its deployment values from</param>
      /// <returns>Returns the component instance.</returns>
      /// <remarks>!!! Not tested !!!</remarks>
      public ComObjectWrapper CreateInstanceWithArgumentsAndContext(string serviceSpecifier, object[] arguments, ComponentContext context)
      {
         Cow.CheckDisposed();
         return ComObjectWrapper.GetObjectWrapper<ComObjectWrapper>(Cow.InvokeMethod("createInstanceWithArgumentsAndContext", serviceSpecifier, arguments, context));
      }

      /// <summary>
      /// Gets the names of all supported services.
      /// </summary>
      /// <returns>Retunbs a sequence of all service names.</returns>
      /// <remarks>!!! Not tested !!!</remarks>
      public string[] GetAvailableServiceNames()
      {
         Cow.CheckDisposed();
         return (string[])Cow.InvokeMethod("getAvailableServiceNames");
      }
   }
}
